import { ArgumentsHost, Catch, ExceptionFilter, HttpException, Inject, BadRequestException } from '@nestjs/common'
import { Request, Response } from 'express'
import { nowDate } from '@/utils/getNowDate'
import { WINSTON_MODULE_PROVIDER } from 'nest-winston'
import { getReasonPhrase } from 'http-status-codes'
import { Logger } from 'winston'

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  constructor(@Inject(WINSTON_MODULE_PROVIDER) private readonly logger: Logger) {}

  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp()
    const request = ctx.getRequest<Request>()
    const response = ctx.getResponse<Response>()
    const status = exception.getStatus()
    const results = exception.getResponse() as any
    const code = results.statusCode

    // 返回的对象
    const responseData = {
      message: results.message || getReasonPhrase(code),
      success: false,
      time: nowDate,
      status,
      path: request.url
    }

    const isArrayMessage = Array.isArray(results.message)
    const isValidationError = isArrayMessage && typeof results.message[0] === 'string' && results.message[0].includes('⓿')
    if (exception instanceof BadRequestException && isValidationError) {
      const message: Array<{ field: string; message: Array<string> }> = []
      results.message.forEach((item) => {
        const [key, val] = item.split('⓿') as [string, string]
        const findData = message.find((item) => item.field === key)
        if (findData) {
          findData.message.push(val)
        } else {
          message.push({ field: key, message: [val] })
        }
      })
      responseData.message = message
    }

    // 记录日志
    const { method, originalUrl, body, query, params, ip } = request
    this.logger.error('HttpException', {
      res: { code, status, message: responseData.message },
      req: { method, url: originalUrl, body, query, params, ip }
    })
    return response.status(status).json(responseData)
  }
}
